package com.example.clock_demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.clock_demo.dto.PunchRecordRequestDTO;
import com.example.clock_demo.entitys.PunchRecord;
import com.example.clock_demo.entitys.Scheduling;
import com.example.clock_demo.entitys.Shift;
import com.example.clock_demo.mapper.PunchRecordMapper;
import com.example.clock_demo.service.PunchRecordService;
import com.example.clock_demo.service.SchedulingService;
import com.example.clock_demo.service.ShiftService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList; // 确保导入
import java.util.List;
import java.util.Map;
import java.util.Optional; // 确保导入
import java.util.stream.Collectors; // 确保导入

/**
 * 原始打卡记录服务实现类
 */
@Service
public class PunchRecordServiceImpl extends ServiceImpl<PunchRecordMapper, PunchRecord> implements PunchRecordService {

    @Autowired
    private SchedulingService schedulingService;
    @Autowired
    private ShiftService shiftService;

    private static final int EARLY_PUNCH_IN_MARGIN_MINUTES = 60;
    private static final int LATE_PUNCH_OUT_MARGIN_MINUTES = 60;

    @Override
    public List<PunchRecord> getValidPunchRecordsForEmployeeByDateRange(String employeeNumber, LocalDate startDate, LocalDate endDate) {
        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);

        QueryWrapper<PunchRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("employee_number", employeeNumber)
                .between("punch_time", startDateTime, endDateTime)
                .eq("is_valid", true)
                .orderByAsc("punch_time");
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public PunchRecord recordPunch(PunchRecordRequestDTO requestDTO) {
        PunchRecord punchRecord = new PunchRecord();
        punchRecord.setTeamName(requestDTO.getTeamName());
        punchRecord.setEmployeeName(requestDTO.getEmployeeName());
        punchRecord.setEmployeeNumber(requestDTO.getEmployeeNumber());
        punchRecord.setPunchTime(requestDTO.getPunchTime());

        punchRecord.setIsValid(false); // 默认设置为无效

        LocalDate punchDate = requestDTO.getPunchTime().toLocalDate();

        // 查询打卡日期及前一天的排班，以处理跨天班次的有效性判断
        List<Scheduling> relevantSchedulings = schedulingService.getSchedulingForEmployeeByDateRange(
                requestDTO.getEmployeeNumber(), punchDate.minusDays(1), punchDate);

        Map<String, Shift> shiftMap = shiftService.list().stream()
                .collect(Collectors.toMap(Shift::getShiftCode, shift -> shift));

        boolean isValidPunch = false;

        for (Scheduling scheduling : relevantSchedulings) {
            Shift shift = shiftMap.get(scheduling.getShiftCode());

            if (shift != null && !"R".equals(shift.getShiftCode()) &&
                    shift.getStartTime() != null && shift.getEndTime() != null) {

                LocalDate shiftDate = scheduling.getScheduleDate();

                // 获取宽限时间配置（默认值）
                int earlyIn = shift.getEarlyPunchInMinutes() != null ? shift.getEarlyPunchInMinutes() : EARLY_PUNCH_IN_MARGIN_MINUTES;
                int lateOut = shift.getLatePunchOutMinutes() != null ? shift.getLatePunchOutMinutes() : LATE_PUNCH_OUT_MARGIN_MINUTES;

                // 班次开始和结束的完整时间点
                LocalDateTime shiftStart = LocalDateTime.of(shiftDate, shift.getStartTime());
                LocalDateTime shiftEnd = shift.getStartTime().isAfter(shift.getEndTime())
                        ? LocalDateTime.of(shiftDate.plusDays(1), shift.getEndTime())
                        : LocalDateTime.of(shiftDate, shift.getEndTime());

                // 上班打卡有效时间窗：班次开始前 earlyIn 分钟 到 班次开始后 60 分钟
                LocalDateTime upperStart = shiftStart.minusMinutes(earlyIn);
                LocalDateTime upperEnd = shiftStart.plusMinutes(60);

                // 下班打卡有效时间窗：班次结束前 60 分钟 到 班次结束后 lateOut 分钟
                LocalDateTime lowerStart = shiftEnd.minusMinutes(60);
                LocalDateTime lowerEnd = shiftEnd.plusMinutes(lateOut);

                // 判断打卡时间是否在任意一个时间窗内
                LocalDateTime punchTime = requestDTO.getPunchTime();
                if ((!punchTime.isBefore(upperStart) && !punchTime.isAfter(upperEnd)) ||
                        (!punchTime.isBefore(lowerStart) && !punchTime.isAfter(lowerEnd))) {
                    isValidPunch = true;
                    break;
                }
            }
        }

        punchRecord.setIsValid(isValidPunch);
        baseMapper.insert(punchRecord);

        return punchRecord;
    }


    @Override
    public Page<PunchRecord> searchPunchRecords(
            LocalDate startDate,
            LocalDate endDate,
            String teamName,
            String employeeName,
            long pageNum,
            long pageSize
    ) {
        // 1. 创建分页对象
        Page<PunchRecord> page = new Page<>(pageNum, pageSize);

        // 2. 构建查询条件
        QueryWrapper<PunchRecord> queryWrapper = new QueryWrapper<>();

        // 时间段查询 (punch_time)
        // 注意：数据库中的 punch_time 是 DATETIME，需要包含时间部分
        // startDateTime 为开始日期的 00:00:00，endDateTime 为结束日期的 23:59:59.999...
        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = endDate.atTime(LocalTime.MAX);
        queryWrapper.between("punch_time", startDateTime, endDateTime);

        // 班组名称模糊查询
        if (teamName != null && !teamName.isEmpty()) {
            queryWrapper.like("team_name", teamName);
        }

        // 姓名模糊查询
        if (employeeName != null && !employeeName.isEmpty()) {
            queryWrapper.like("employee_name", employeeName);
        }

        // 默认按打卡时间降序排列（最新打卡在前）或按工号、打卡时间升序排列
        queryWrapper.orderByDesc("punch_time"); // 或者 .orderByAsc("employee_number", "punch_time");

        // 3. 执行分页查询
        return baseMapper.selectPage(page, queryWrapper);
    }
}